## 空间注意力模块

import torch
import torch.nn as nn
import torch.nn.functional as F
from .eca_module import ECALayer

class SpatialAttention(nn.Module):
    def __init__(self, kernel_size=7):
        super(SpatialAttention, self).__init__()
        self.conv = nn.Conv2d(2, 1, kernel_size, padding=kernel_size // 2, bias=False)
        self.sigmoid = nn.Sigmoid()

    def forward(self, x):
        # x: (B, C, H, W)
        avg_out = torch.mean(x, dim=1, keepdim=True)         # (B, 1, H, W)
        max_out, _ = torch.max(x, dim=1, keepdim=True)       # (B, 1, H, W)
        x_cat = torch.cat([avg_out, max_out], dim=1)         # (B, 2, H, W)
        attention = self.sigmoid(self.conv(x_cat))           # (B, 1, H, W)
        return x * attention


class ECSALayer(nn.Module):
    def __init__(self, channels, gamma=2, b=1, spatial_kernel=7):
        super(ECSALayer, self).__init__()
        self.channel_att = ECALayer(channels, gamma=gamma, b=b)
        self.spatial_att = SpatialAttention(kernel_size=spatial_kernel)

    def forward(self, x):
        x_out = self.channel_att(x)
        x_out = self.spatial_att(x_out)
        return x_out
